package edu.hznu.retroSnakerPlanServer.utils;

import edu.hznu.retroSnakerPlanServer.dto.RequestMsg;
import edu.hznu.retroSnakerPlanServer.entity.Food;
import edu.hznu.retroSnakerPlanServer.entity.ReqType;
import edu.hznu.retroSnakerPlanServer.entity.SnakeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.DatagramPacket;
import java.util.ArrayList;
import java.util.List;

/**
 * create by Cliven on 2018-05-31 16:30
 * 请求实体构造器
 *
 * @author Cliven
 */
public class RequestBuilder {

    private static final Logger log = LoggerFactory.getLogger(RequestBuilder.class);

    public static RequestMsg build(DatagramPacket datagramPacket) {
        Integer len = datagramPacket.getLength();
        Byte[] recv = new Byte[len];
        byte[] source = datagramPacket.getData();

        // 复制请求体的重内容
        for (int i = 0; i < len; i++) {
            recv[i] = source[i];
        }
        return build(recv);
    }

    /**
     * 根据字节数组构造请求实体
     *
     * @param requestData 解析数据
     * @return 实体
     * @author Cliven
     * @since 2018-05-31 21:46:53
     */
    public static RequestMsg build(Byte[] requestData) {

        try {
            Integer offset = 0;
            RequestMsg requestMsg = new RequestMsg();

            Integer reqType = requestData[offset++] & 0xFF;
//            log.debug("reqType: {}", reqType.toString());
            ReqType.check(reqType);
            // 如果是请求加入游戏的，那么直接处理返还即可
            if (ReqType.NO_ID.equals(reqType)) {
                return requestMsg.setReqType(reqType);
            }

            Integer msgCmt = requestData[offset++] & 0xFF;
//            log.debug("msgCmt: {}", msgCmt.toString());
            Integer id = requestData[offset++] & 0xFF;
//            log.debug("id: {}", id.toString());

            // 判断请求类型，如果是死亡，则解析击杀者的ID
            if (ReqType.DEAD.equals(reqType)) {
                requestMsg.setKiller(requestData[offset++] & 0xFF);
            }

            // 用户信息长度 4 byte
            Integer playerInfoLen = ByteUtils.byteToInt(requestData, offset);
//            log.debug("playerInfoLen: {}", playerInfoLen.toString());

            offset += 4;
            // 计算剩余用户信息
            int len = playerInfoLen / SnakeNode.SIZE;
            List<SnakeNode> playerInfo = new ArrayList<>(len);
            for (int i = 0; i < len; i++) {
//                if (i != 0) {
//                    offset = offset + SnakeNode.SIZE;
//                }
                playerInfo.add(SnakeNode.getInstance(requestData, offset));
                offset = offset + SnakeNode.SIZE;
            }
//            offset += SnakeNode.SIZE;
            // 吃掉的食物 4 byte
            Integer eatsLen = ByteUtils.byteToInt(requestData, offset);
//            log.debug("eatsLen: {}", eatsLen.toString());

            offset += 4;
//            Integer eatsLen = (int) requestData[offset++];
            len = eatsLen / Food.SIZE;
            List<Food> eats = new ArrayList<>(len);
            for (int i = 0; i < len; i++) {
//                offset += i * Food.SIZE;
                eats.add(Food.getInstance(requestData, offset));
                offset +=  Food.SIZE;
            }

            return requestMsg.setReqType(reqType)
                    .setMsgCnt(msgCmt)
                    .setId(id)
                    .setPlayerInfo(playerInfo)
                    .setEats(eats);

        } catch (RuntimeException e) {
            throw new IllegalArgumentException("can not resolve message,"
                    + e.getMessage()
                    + "\ncontent: \n"
                    + ByteUtils.bytesToHex(requestData), e);
        }
    }
}
